package myTest;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

/**
 * 服务器端
 * 已实现功能:
 * 1:创建端口(端口号默认8088)
 * 2:记录系统日志和用户消息(系统语句标识符号:">   >   >   >   >   >   >   >   >")
 * 3:接收客户端消息
 * 4:让所有已连接用户接收消息(给所有用户端转发某一用户端的消息)
 * 创建的方法和类:
 * 1:构造方法
 * 2:获取当前时间方法(String)
 * 3:记录日志信息
 * 4:启动方法
 */
public class ServerDemo {
    private ServerSocket serverSocket;
    private ArrayList<PrintWriter> allOut = new ArrayList<>();

    public ServerDemo() {
        try {
            System.out.println("服务器正在创建....");
            log(">   >   >   >   >   >   >   >   >服务器正在创建...");
            serverSocket = new ServerSocket(8088);
            System.out.println("服务器创建成功!端口号:8088");
            log(">   >   >   >   >   >   >   >   >服务器创建成功!端口号8888");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取当前时间
     */
    public String times() {
        SimpleDateFormat sdf = new SimpleDateFormat();// 格式化时间
        sdf.applyPattern("yyyy-MM-dd HH:mm:ss");// a为am/pm的标记
        Date loginDate = new Date();// 获取当前时间
        String loginTime = sdf.format(loginDate);
        return loginTime;
    }

    /**
     * 用来创建日志
     *
     * @param s 需要被记录的文档内容
     */
    public void log(String s) {
        try {
            PrintWriter pw = new PrintWriter(
                    new BufferedWriter(
                            new OutputStreamWriter(
                                    new FileOutputStream("练习的日志文件", true),
                                    StandardCharsets.UTF_8)), true);
            if(s.startsWith(">   >   >   >   >   >   >   >   >")){
                pw.println(s);
            }else{
                pw.println(times()+"▣" + s);
            }
            pw.close();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 启动方法
     */
    public void start(){
        try {
            while (true) {
                System.out.println("正在连接客户端.....");
                log(">   >   >   >   >   >   >   >   >正在连接客户端...");
                Socket socket = serverSocket.accept();
                System.out.println("第"+(allOut.size()+1)+"个客户端连接成功!");
                log(">   >   >   >   >   >   >   >   >第"+(allOut.size()+1)+"个客户端连接成功");
                log(">   >   >   >   >   >   >   >   >客户端IP地址:" + socket.getInetAddress().getHostAddress());

                //将用户发送到服务端的所有消息群发给所有用户端(分配一个线程)
                ClientHardle clientHardle = new ClientHardle(socket);
                Thread t = new Thread(clientHardle);
                t.start();
            }


        } catch (IOException e) {
            throw new RuntimeException(e);
        }


    }


    public class ClientHardle implements Runnable{
        private Socket socket;
        private String host;

        public ClientHardle(Socket socket) {
            this.socket = socket;
            host = socket.getInetAddress().getHostAddress();
        }

        @Override
        public void run() {
            PrintWriter pw = null ;
            try {
                 pw = new PrintWriter(
                        new BufferedWriter(
                                new OutputStreamWriter(
                                        socket.getOutputStream(), StandardCharsets.UTF_8)),true);
                allOut.add(pw);
                BufferedReader br = new BufferedReader(
                        new InputStreamReader(
                                socket.getInputStream(), StandardCharsets.UTF_8));
                String message ;
                //给每一个用户发送消息
                while ((message = br.readLine()) != null) {
                    log(host + ":" + message);
                    for (PrintWriter p : allOut) {
                        p.println(host+":"+message);
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }finally {
                try {
                    pw.close();
                    allOut.remove(pw);
                    socket.close();
                    for (PrintWriter p : allOut) {
                        p.println(host + "已离线,当前在线人数:" + allOut.size());
                    }
                    log(">   >   >   >   >   >   >   >   >"+host + "已离线,实时人数" + allOut.size()+"人");
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        }

    public static void main(String[] args) {
        ServerDemo sd = new ServerDemo();
        sd.start();
    }
    }

